<?php
/**
 * Created by JetBrains PhpStorm.
 * User: Silence
 * Date: 3/30/12
 * Time: 12:46 AM
 * To change this template use File | Settings | File Templates.
 */
include_once('event.php');
include_once('api.php');

class ApiTest extends PHPUnit_Framework_TestCase
{
    /**
     * @expectedException ErrorException
     * @expectedExceptionMessage Null object.
     */
    public function test_check_attr_null()
    {
        check_attr();
    }

    /**
     * @expectedException ErrorException
     * @expectedExceptionMessage No attribute 'id'.
     */
    public function test_check_attr_singleton()
    {
        check_attr(new stdClass(), 'id');
    }

    /**
     * @expectedException ErrorException
     * @expectedExceptionMessage No attribute 'missing'.
     */
    public function test_check_attr_array()
    {
        $data = new stdClass();
        $data->id = 1;
        $data->text = "Good job";
        check_attr($data, array('id', 'text', 'missing'));
    }

    public function test_array_intersect()
    {
        $a1 = array("1", "2", "3");
        $a2 = array("1", "2", "5");
        $this->assertEquals(array("1", "2"), array_intersect($a1, $a2));
    }

    public function test_array_stdClass()
    {
        $a = array("a" => "1", "b" => "2");
        $o = new stdClass();
        $o->a = "1";
        $o->b = "2";
        $this->assertEquals($a, (array)$o);
        //        $this->assertEquals($o, new stdClass($a));
    }

    public function test_implode_explode()
    {
        $array = array("id", "name");
        $this->assertEquals(implode("`,`", $array), "id`,`name");
    }

    public function test_get_keys_values_pair()
    {
        $data = new stdClass();
        $data->id = "id";
        $data->name = "name";
        $pair = get_keys_values_pair($data, array('id', 'name', 'start_date', 'end_date'));
        $this->assertEquals(array("id", "name"), $pair[0]);
        $this->assertEquals(array("id", "name"), $pair[1]);
    }

    public function test_get_key_value_pairs()
    {
        $data = new stdClass();
        $data->id = "id";
        $data->name = "name";
        $data->time = "2012";
        $this->assertEquals("`id`='id',`name`='name'", get_key_value_pairs($data, array("id", "name")));
        $this->assertEquals("", get_key_value_pairs($data, array()));
    }
}

abstract class AppDatabaseTest extends PHPUnit_Extensions_Database_TestCase
{
    // only instantiate pdo once for test clean-up/fixture load
    static private $pdo = null;

    // only instantiate PHPUnit_Extensions_Database_DB_IDatabaseConnection once per test
    private $conn = null;

    final public function getConnection()
    {
        if ($this->conn === null) {
            if (self::$pdo == null) {
                self::$pdo = new PDO('mysql:host=localhost;dbname=event_manager', 'root', '');
            }
            $this->conn = $this->createDefaultDBConnection(self::$pdo, "event_manager");
        }

        return $this->conn;
    }
}

class EventTest extends AppDatabaseTest
{
    private $scope = 10;

    public function test_create()
    {
        db_prepare();
        $data_set = array('event' => array(), 'event_basic' => array());
        for ($i = 1; $i < $this->scope; $i++)
        {
            $data = new stdClass();
            $data->name = "New event " . $i;
            $data->parentId = 0;

            $event = new Event($data);
            $this->assertEquals($i, $this->getConnection()->getRowCount('event'));
            $this->assertEquals($i, $this->getConnection()->getRowCount('event_basic'));
            $data_set['event'][] = array('id' => $i, 'parentId' => 0, 'leaf' => 0, 'status' => 1);
            $data_set['event_basic'][] = array('id' => $i, 'name' => $data->name, 'start_date' => "", 'end_date' => "");
        }

        $event_table = $this->getConnection()->createDataSet(array('event'));
        $expeced_event_table = new DbUnit_ArrayDataSet(array('event' => $data_set['event']));
        $this->assertDataSetsEqual($expeced_event_table, $event_table);
        $event_basic_table = $this->getConnection()->createDataSet(array('event_basic'));
        $expeced_event_basic_table = new DbUnit_ArrayDataSet(array('event_basic' => $data_set['event_basic']));
        $this->assertDataSetsEqual($expeced_event_basic_table, $event_basic_table);
    }

    /**
     *
     */
    public function test_read()
    {
        db_prepare();
        $data1 = new stdClass();
        $data1->parentId = 0;
        $data1->name = "folder 1";

        $data2 = new stdClass();
        $data2->parentId = 1;
        $data2->name = "folder 2";

        $data3 = new stdClass();
        $data3->parentId = 1;
        $data3->name = "folder 3";

        $data4 = new stdClass();
        $data4->parentId = 2;
        $data4->leaf = 1;
        $data4->name = "folder 4";

        $e1 = new Event($data1);
        $e2 = new Event($data2);
        $e3 = new Event($data3);
        $e4 = new Event($data4);

        $non_recursive = array(
            'id' => 1,
            'name' => 'folder 1',
            'start_date' => '',
            'end_date' => '',
            'parentId' => 0,
            'leaf' => 0,
            'status' => 1,
            'children' => array(
                array(
                    'id' => 2,
                    'name' => 'folder 2',
                    'start_date' => '',
                    'end_date' => '',
                    'parentId' => 1,
                    'leaf' => 0,
                    'status' => 1
                ),
                array(
                    'id' => 3,
                    'name' => 'folder 3',
                    'start_date' => '',
                    'end_date' => '',
                    'parentId' => 1,
                    'leaf' => 0,
                    'status' => 1
                )
            )
        );
        $this->assertEquals($non_recursive, $e1->read(array("status", "leaf", "name", "start_date", "end_date"), TRUE, FALSE));

        $recursive = array(
            'id' => 1,
            'name' => 'folder 1',
            'start_date' => '',
            'end_date' => '',
            'parentId' => 0,
            'leaf' => 0,
            'status' => 1,
            'children' => array(
                array(
                    'id' => 2,
                    'name' => 'folder 2',
                    'start_date' => '',
                    'end_date' => '',
                    'parentId' => 1,
                    'leaf' => 0,
                    'status' => 1,
                    'children' => array(
                        array(
                            'id' => 4,
                            'name' => 'folder 4',
                            'start_date' => '',
                            'end_date' => '',
                            'parentId' => 2,
                            'leaf' => 1,
                            'status' => 1,
                        )
                    )
                ),
                array(
                    'id' => 3,
                    'name' => 'folder 3',
                    'start_date' => '',
                    'end_date' => '',
                    'parentId' => 1,
                    'leaf' => 0,
                    'status' => 1
                )
            )
        );
        $this->assertEquals($recursive, $e1->read(array("status", "leaf", "name", "start_date", "end_date"), TRUE, TRUE));

        $this->assertEquals($non_recursive, $e1->read(array("status", "leaf", "name", "start_date", "end_date"), FALSE, TRUE));

    }

    public function test_load()
    {
        db_prepare();
        $data = new stdClass();
        $data->name = "name";
        $data->parentId = 0;
        $data->start_date = "start_date";
        $event = new Event($data);

        $res = array();
        $res['name'] = "name";
        $res['start_date'] = "start_date";
        $res['id'] = 1;
        $res['parentId'] = 0;
        $res['end_date'] = '';

        $this->assertEquals($res, $event->load(array("end_date")));
    }

    /**
     * @depends test_create
     */
    public function test_update()
    {
        $this->test_create();
        db_prepare();
        $data_set = array('event' => array(), 'event_basic' => array());
        for ($i = 1; $i < $this->scope; $i++)
        {
            $data = new stdClass();
            $data->id = $i;
            $data->parentId = $i - 1;
            $data->leaf = $i % 2;
            $data->status = 1 - $i % 2;
            if (1 - $i % 2) {
                $data->name = "New folder $i";
                $data->start_date = "start_date $i";
                $data->end_date = "end_date $i";

                $data_set['event_basic'][] = array('id' => $i, 'name' => "New folder $i", 'start_date' => "start_date $i", 'end_date' => "end_date $i");
            }
            $event = new Event($data);
            $event->update();

            $data_set['event'][] = array('id' => $i, 'parentId' => $i - 1, 'leaf' => $i % 2, 'status' => 1 - $i % 2);
        }

        $event_table = $this->getConnection()->createDataSet(array('event'));
        $expeced_event_table = new DbUnit_ArrayDataSet(array('event' => $data_set['event']));
        $this->assertDataSetsEqual($expeced_event_table, $event_table);
        $event_basic_table = new PHPUnit_Extensions_Database_DataSet_QueryDataSet($this->getConnection());
        $event_basic_table->addTable('event_basic', 'SELECT * FROM `event_basic` WHERE `id`%2=0');
        $expeced_event_basic_table = new DbUnit_ArrayDataSet(array('event_basic' => $data_set['event_basic']));
        $this->assertDataSetsEqual($expeced_event_basic_table, $event_basic_table);
    }

    /**
     * @depends test_create
     */
    public function test_delete()
    {
        $this->test_create();
        db_prepare();
        for ($i = 1; $i < $this->scope; $i++)
        {
            $data = new stdClass();
            $data->id = $i;
            $event = new Event($data);
            $event->delete();
            $this->assertEquals($this->scope - 1 - $i, $this->getConnection()->getRowCount('event'));
            $this->assertEquals($this->scope - 1 - $i, $this->getConnection()->getRowCount('event_basic'));
        }
    }


    /**
     * Returns the test dataset.
     *
     * @return PHPUnit_Extensions_Database_DataSet_IDataSet
     */
    protected function getDataSet()
    {
        return new DbUnit_ArrayDataSet(array(
            'event_basic' => array(),
            'event' => array(
//                array('id' => 1, 'content' => 'Hello buddy!', 'user' => 'joe', 'created' => '2010-04-24 17:15:23'),
//                array('id' => 2, 'content' => 'I like it!',   'user' => null,  'created' => '2010-04-26 12:14:20'),
            ),

        ));
    }

    public function getSetUpOperation()
    {
        $cascadeTruncates = TRUE; //if you want cascading truncates, false otherwise
        //if unsure choose false

        return new PHPUnit_Extensions_Database_Operation_Composite(array(
            new PHPUnit_Extensions_Database_Operation_MySQL55Truncate($cascadeTruncates),
            PHPUnit_Extensions_Database_Operation_Factory::INSERT()
        ));
    }
}


class PHPUnit_Extensions_Database_Operation_MySQL55Truncate extends PHPUnit_Extensions_Database_Operation_Truncate
{
    public function execute(PHPUnit_Extensions_Database_DB_IDatabaseConnection $connection, PHPUnit_Extensions_Database_DataSet_IDataSet $dataSet)
    {
        $connection->getConnection()->query("SET @PHAKE_PREV_foreign_key_checks = @@foreign_key_checks");
        $connection->getConnection()->query("SET foreign_key_checks = 0");
        parent::execute($connection, $dataSet);
        $connection->getConnection()->query("SET foreign_key_checks = @PHAKE_PREV_foreign_key_checks");
    }
}

class DbUnit_ArrayDataSet extends PHPUnit_Extensions_Database_DataSet_AbstractDataSet
{
    /**
     * @var array
     */
    protected $tables = array();

    /**
     * @param array $data
     */
    public function __construct(array $data)
    {
        foreach ($data AS $tableName => $rows) {
            $columns = array();
            if (isset($rows[0])) {
                $columns = array_keys($rows[0]);
            }

            $metaData = new PHPUnit_Extensions_Database_DataSet_DefaultTableMetaData($tableName, $columns);
            $table = new PHPUnit_Extensions_Database_DataSet_DefaultTable($metaData);

            foreach ($rows AS $row) {
                $table->addRow($row);
            }
            $this->tables[$tableName] = $table;
        }
    }

    protected function createIterator($reverse = FALSE)
    {
        return new PHPUnit_Extensions_Database_DataSet_DefaultTableIterator($this->tables, $reverse);
    }

    public function getTable($tableName)
    {
        if (!isset($this->tables[$tableName])) {
            throw new InvalidArgumentException("$tableName is not a table in the current database.");
        }

        return $this->tables[$tableName];
    }
}
